iT邦幫忙

2022 iThome 鐵人賽

DAY 17
0
Mobile Development

在 iOS 開發路上的大小事2系列 第 17

【在 iOS 開發路上的大小事2-Day17】Application Extension 簡介

  • 分享至 

  • xImage
  •  

前情提要

Application Extension 是從 iOS 8 開始出現的一種使用者互動介面

Extension 顧名思義就是擴展的意思,而 Application Extension 就是 App 的擴展

所以說 Application Extension 本身並不是單獨一個 App,而是需要仰賴 App 才能運作的

而 Application Extension 本身的 LifeCycle (生命週期) 也跟一般 App 不同

有些是需要使用者手動啟動,有些則是可以在各個 App 中被啟動

像是鍵盤輸入法 (Custom Keyboard Extension)、密碼自動填入 (AutoFill Credential Provider) 等就是需要使用者手動去啟動
而 Share Extension、Action Extension 這兩個則是可以在各個 App 中被啟動

LifeCycle 生命週期

前面有說到 Application Extension 的 LifeCycle 跟一般 App 是不一樣的
讓我們來看一下 Application Extension 是怎麼運作的


▲ 圖取自 Apple Developer Documentation

  1. 使用者啟動 Application Extension
  2. 系統啟動 Application Extension
  3. 執行 Application Extension 內的程式
  4. 系統關閉 Application Extension

與 App 之間的溝通

開頭有說到 Application Extension 是需要依賴 App 本體才能運作

既然是這樣,那麼 Application Extension 跟 App 也是可以相互溝通的

讓我們來看一下 Application Extension 跟 App 之間是怎麼相互溝通

簡單版


▲ 圖取自 Apple Developer Documentation

進階版


▲ 圖取自 Apple Developer Documentation

名詞解說

Containing App:App 本體

App Extension:Containing App 的擴展,需依賴於 Containing App

Host App:呼叫 App Extension 的 App

在簡單版中,可以看到 Host App 呼叫的是 App Extension 而不是 Containing App
App Extension 與 Host App兩者之間可以進行 Request 跟 Response 溝通

而 App Extension 與 Containing App 之間以虛線標示是因為
App Extension 執行的時候 Containing App 是可以不用執行的
也就是 App Extension 與 Containing App 之間是可以不用有溝通的

接著,我們來看進階版,App Extension 與 Host App 之間的溝通一樣
但與 Containing App 之間卻不一樣了,兩者之間多了 Open URLShared resources 互動

Open URL

首先是 Open URL,這個是只有 Widget Extension 才能使用
透過下面這個 Function 來實作,用於點擊 Widget 後,跳回 Containing App

func open(_ URL: URL, completionHandler: ((Bool) -> Void)? = nil)

Shared resources

Containing App 與 App Extension 之間有時候會需要有資料共用、傳輸的需求
那一般來說是做不到的,主要是因為 iOS 系統讓 App、App Extension 都是透過 Sandbox (沙盒) 運作的,所以兩者之間是八竿子打不著的
我們可以透過下面這個例子,來知道如果 App 中有使用 SQLite 的話,會在兩邊都建立一個 db 檔

# Containing App 建立的 db 檔
/var/mobile/Containers/Data/Application/E5E6E516-0163-4754-9D10-A5F6C33A6261/Documents/app.db

# App Extension 建立的 db 檔
/var/mobile/Containers/Data/PluginKitPlugin/0A99BB23-E261-4AB9-8DA1-29EFA6E2649E/Documents/app.db

從上面路徑可以看到從「/var/mobile/Containers/Data/」後面兩者的路徑就不一樣了

Containing App 是建立在「Application/」下,而 App Extension 是建立在「PluginKitPlugin/」

難怪會在 Containing App 跟 App Extension 兩邊都各建立一個 db 檔

那該怎麼處理呢?
我們可以透過 App Groups 來讓 Containing App 跟 App Extension 共同讀寫同一個區域

App Groups

這裡就稍微說一下,App Groups 要如何開啟 (Containing App 跟 Extension 開啟方法都一樣)

Containing App 跟 App Extension 兩邊都要開啟 App Groups 才行喔!

0. TARGETS -> <TARGETS NAME> -> Signing & Capabilities -> Signing 選 Apple 付費開發者帳號
1. TARGETS -> <TARGETS NAME> -> Signing & Capabilities -> App Groups
2. App Groups -> + -> 輸入 group.<你想取的名稱>

接著有兩個方式可以讓 Containing App 跟 App Extension 共同存取資料

  1. UserDefaults
  2. FileManager

UserDefaults

UserDefaults(suiteName: "group.<你想取的名稱>")

FileManager

FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.<你想取的名稱>")

不能在 Application Extension 做的事情

從 Apple Developer Documentation 中可以知道
有些事情是不能在 Application Extension 做的,如下圖


▲ 圖取自 Apple Developer Documentation

不負責翻譯如下

  1. 不能存取 sharedApplication 物件,所以不能使用 sharedApplication 物件中的任何 Methods
  2. 不能使用任何被標記 NS_EXTENSION_UNAVAILABLE 的 API 或類似的標記,
    以及 unavailable Framework 中的任何 API,像是 HealthKit、EventKit UI Framework
  3. 不能在 iOS 裝置上使用相機與麥克風
    (iMessage App 可以,只需要在 Info.plist 中新增 NSCameraUsageDescription、NSMicrophoneUsageDescription)
  4. 執行長時間的背景任務
  5. 透過 AirDrop 來接收資料

總結

Application Extension 幫 App 新增許多可玩性

在下一篇會以 AutoFill Credential Provider 來當作範例實作 App Extension


上一篇
【在 iOS 開發路上的大小事2-Day16】非黑即白的 Result type
下一篇
【在 iOS 開發路上的大小事2-Day18】Password AutoFill App Extension
系列文
在 iOS 開發路上的大小事230
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言